package spring.spel;

import java.lang.reflect.Method;
import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.testng.Assert;
import org.testng.annotations.Test;


public class SpELTest {
    @Test
    public void helloWorld() {

        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("('Hello'+'World').concat(#end)");
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("end", "!");
        Assert.assertEquals("HelloWorld!", expression.getValue(context));

    }


    @Test
    public void testClassTypeExpression() {
        ExpressionParser parser = new SpelExpressionParser();
        Class<String> result1 = parser.parseExpression("T(String)").getValue(Class.class);
        Assert.assertEquals(String.class, result1);

        String expression2 = "T(spring.learn.spel.SpELTest)";
        Class<String> result2 = parser.parseExpression(expression2).getValue(Class.class);
        Assert.assertEquals(SpELTest.class, result2);

        int result3 = parser.parseExpression("T(Integer).MAX_VALUE").getValue(int.class);
        Assert.assertEquals(Integer.MAX_VALUE, result3);

        int result4 = parser.parseExpression("T(Integer).parseInt('1')").getValue(int.class);
        Assert.assertEquals(1, result4);
    }

    @Test
    public void testConstructorExpression() {
        ExpressionParser parser = new SpelExpressionParser();
        String result1 = parser.parseExpression("new String('haha')").getValue(String.class);
        Assert.assertEquals("haha", result1);
        Date result2 = parser.parseExpression("new java.util.Date()").getValue(Date.class);
        Assert.assertNotNull(result2);
    }

    @Test
    public void testVariableExpression() {
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("variable", "haha");
        context.setVariable("variable", "haha");
        String result1 = parser.parseExpression("#variable").getValue(context, String.class);
        Assert.assertEquals("haha", result1);
        context = new StandardEvaluationContext("haha");
        String result2 = parser.parseExpression("#root").getValue(context, String.class);
        Assert.assertEquals("haha", result2);
        String result3 = parser.parseExpression("#this").getValue(context, String.class);
        Assert.assertEquals("haha", result3);
    }

    @Test
    public void testFunctionExpression() throws SecurityException, NoSuchMethodException {
        ExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext context = new StandardEvaluationContext();
        Method parseInt = Integer.class.getDeclaredMethod("parseInt", String.class);

        context.registerFunction("parseInt", parseInt);
        context.setVariable("parseInt2", parseInt);
        String expression1 = "#parseInt('3')==#parseInt2('3')";
        boolean result1 = parser.parseExpression(expression1).getValue(context, boolean.class);
        Assert.assertEquals(true, result1);
    }

    @Test
    public void testAssignExpression() {
        ExpressionParser parser = new SpelExpressionParser();
    }

    @Test
    public void testAnnotationExpression() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("src/main/resources/el2.xml");
        SpELBean helloBean1 = ctx.getBean("helloBean1", SpELBean.class);
        Assert.assertEquals("Hello World", helloBean1.getValue());
        SpELBean helloBean2 = ctx.getBean("helloBean2", SpELBean.class);
        Assert.assertEquals("haha", helloBean2.getValue());
    }

    @Test
    public void testPrefixExpression() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("src/main/resources/el3.xml");
        SpELBean hello1 = ctx.getBean("helloBean1", SpELBean.class);
        Assert.assertEquals("#{'Hello' + world}", hello1.getValue());
        SpELBean helloBean2 = ctx.getBean("helloBean2", SpELBean.class);
        Assert.assertEquals("Hello World!", helloBean2.getValue());

    }
}
